﻿using System;
using System.Collections.ObjectModel;
using System.Linq;
using Microsoft.Practices.Prism.Events;
using Reactor.Entities;
using Reactor.Environment;
using Reactor.Messages.Replies.Diagnostics;
using Reactor.Messages.Requests.Diagnostics;
using Reactor.MiniManager.Events;

namespace Reactor.MiniManager.ViewModels
{
    public class BusDiagnosticsViewModel : ViewModelBase
    {
        #region Fields

        private readonly ReactorCoreEntity _reactorCore;
        private readonly IEventAggregator _eventAggregator;

        #endregion

        /// <summary>
        /// Initializes a new instance of the <see cref="BusDiagnosticsViewModel"/> class.
        /// </summary>
        /// <param name="reactorCore">The reactor core.</param>
        /// <param name="eventAggregator">The event aggregator.</param>
        public BusDiagnosticsViewModel(ReactorCoreEntity reactorCore, IEventAggregator eventAggregator)
        {
            if (reactorCore == null) throw new ArgumentNullException("reactorCore");
            if (eventAggregator == null) throw new ArgumentNullException("eventAggregator");

            _reactorCore = reactorCore;
            _eventAggregator = eventAggregator;
            QueueEndpoints = new ObservableCollection<EndpointDestinationViewModel>();
            TopicEndpoints = new ObservableCollection<EndpointDestinationViewModel>();

            _eventAggregator.GetEvent<BusMessageReceived<EndpointDiagnosticsResponse>>().Subscribe(HandleEndpointDiagnosticsResponse);

            // Issue a request so we can be notified of bus diagnostics information
            var request = new EndpointDiagnosticsRequest();
            Context.ServiceBus.Request(request);
        }

        public string Name
        {
            get { return _reactorCore.Identifier.Name; }
        }

        public ObservableCollection<EndpointDestinationViewModel> QueueEndpoints { get; set; }

        public ObservableCollection<EndpointDestinationViewModel> TopicEndpoints { get; set; }

        private void HandleEndpointDiagnosticsResponse(EndpointDiagnosticsResponse diagnosticsResponse)
        {
            ExecuteOnUiThread(UpdateEndpoints, diagnosticsResponse);
        }

        private void UpdateEndpoints(EndpointDiagnosticsResponse diagnosticsResponse)
        {
            TopicEndpoints.Clear();
            QueueEndpoints.Clear();

            // Add to or update destination
            foreach (var map in diagnosticsResponse.DestinationToMessageTypesMaps)
            {
                var m = map;
                var isQueue = m.DestinationName.StartsWith(Messaging.Destination.TypedQueuePrefix);
                var vm = new EndpointDestinationViewModel(m.DestinationName);
                vm.Refresh(m);

                if (isQueue)
                    QueueEndpoints.Add(vm);
                else
                    TopicEndpoints.Add(vm);
            }
        }

        protected override void Dispose(bool disposing)
        {
            _eventAggregator.GetEvent<BusMessageReceived<EndpointDiagnosticsResponse>>().Unsubscribe(HandleEndpointDiagnosticsResponse);
        }
    }
}
